import Graphics.Rendering.OpenGL as GL
import Graphics.UI.GLFW as GLFW

import Utils
import LoadShaders

import Foreign.Marshal.Array
import Foreign.Ptr
import Foreign.Storable

data Descriptor = Descriptor ArrayIndex NumArrayIndices

bufferOffset :: Integral a => a -> Ptr b
bufferOffset  = plusPtr nullPtr . fromIntegral

v2 :: (a, a) -> Vertex2 a
v2  (x, y) = Vertex2 x y
main :: IO ()
main = do
  GLFW.init
  GLFW.defaultWindowHints
  Just win <- GLFW.createWindow 640 480 "GLFW Demo" Nothing Nothing
  GLFW.makeContextCurrent (Just win)
  GLFW.setWindowSizeCallback win (Just resizeWindow)
  GLFW.setKeyCallback win (Just keyPressed)
  GLFW.setWindowCloseCallback win (Just shutdown)

  let vertics = [
          v2 (-0.90, -0.90)
        , v2 (0.85, -0.90)
        , v2 (-0.90, 0.85)
        , v2 (0.90, -0.85)
        , v2 (0.90, 0.90)
        , v2 (-0.85, 0.90)] :: [Vertex2 GLfloat]

      vertNum = length vertics
  --program
  program <- loadShaders [
                         ShaderInfo VertexShader (FileSource "src/shader.vert")
                           , ShaderInfo FragmentShader (FileSource "src/shader.frag")]
  currentProgram $= Just program
  --buffer data
  vbo <- genObjectName
  bindBuffer ArrayBuffer $= Just vbo
  withArray vertics $ \ptr -> do
    let size = fromIntegral $ vertNum * sizeOf (head vertics)
    bufferData ArrayBuffer $= (size, ptr, StaticDraw)
  --attribute in shader
  let firstIndex = 0
  vPosition <- get $ attribLocation program "vPosition"
  vertexAttribPointer vPosition $= (ToFloat, VertexArrayDescriptor 2 Float 0 (bufferOffset firstIndex))
  vertexAttribArray vPosition $= Enabled
  --uv in shader
  let uv = [
          TexCoord2 0.0 0.0
        , TexCoord2 1.0 0.0
        , TexCoord2 0.0 1.0
        , TexCoord2 1.0 0.0
        , TexCoord2 1.0 1.0
        , TexCoord2 0.0 1.0
           ] :: [TexCoord2 GLfloat]

  tbo <- genObjectName
  bindBuffer ArrayBuffer $= Just tbo
  withArray uv $ \ptr -> do
    let size = fromIntegral (vertNum * sizeOf (head uv))

    bufferData ArrayBuffer $= (size, ptr, StaticDraw)

  uvCoords <- get $ attribLocation program "uvCoords"
  vertexAttribPointer uvCoords $= (ToFloat, VertexArrayDescriptor 2 Float 0 (bufferOffset firstIndex))
  vertexAttribArray uvCoords $= Enabled

  tx <- loadTex "img/test.png"
  texture Texture2D $= Enabled
  activeTexture $= TextureUnit 0
  textureBinding Texture2D $= Just tx
  --display
  draw win $ Descriptor firstIndex (fromIntegral vertNum)

  GLFW.destroyWindow win
  GLFW.terminate

draw :: Window -> Descriptor -> IO ()
draw win des@(Descriptor firstIndex vertNum) = do
  GL.clearColor $= Color4 1 0 0 1
  GL.clear [ColorBuffer]
  GL.drawArrays Triangles firstIndex vertNum

  GLFW.swapBuffers win
  GLFW.pollEvents
  draw win des
